package com.portal.framework.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.LockMode;

import com.portal.framework.exception.AppException;
import com.portal.framework.page.PagerResult;

/**
 * DAO接口,定义DAO的应有的公共方法 泛型C指的是要实现哪个类的DAO.一般为DTO,PK 代表ID的类型 <BR>
 * <BR>
 * <BR>
 * 用法:<BR>
 * XXDTO的DAO接口,主键类型为 Long <BR>
 * public interface XXIDAO extends BaseIDAO&lt;XXDTO, Long&gt; <BR>
 * 
 * @author 卢烁波
 * @date 2007-3-10
 */
public interface BaseIDAO<C, PK extends Serializable> {

	/**
	 * 得到DAO要实现的哪个类的Class.
	 */
	public abstract Class<C> getPersistentClass();

	/**
	 * 通过 SQL 进行删除
	 * 
	 * @deprecated {@link #executeQuery(String)}
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	public int deleteBySQL(String sql) throws SQLException;

	/**
	 * 传入一个对象,保存或更新该对象
	 * 
	 * @param obj
	 * @return
	 */
	public C saveOrUpdate(C obj);

	/**
	 * 保存对象
	 * 
	 * @param obj
	 * @return
	 */
	public C create(C obj);

	/**
	 * 更新对象
	 * 
	 * @param obj
	 * @return
	 */
	public C update(C obj);

	/**
	 * 批量保存
	 * 
	 * @param objs
	 * @return
	 */
	public List<C> createBatch(List<C> objs);

	/**
	 * 批量保存
	 * 
	 * @param objs
	 * @return
	 */
	public Set<C> createBatch(Set<C> objs);

	/**
	 * 批量更新
	 * 
	 * @param objs
	 * @return
	 */
	public List<C> updateBatch(List<C> objs);

	/**
	 * 删除传入的对象

	 * 
	 * @param obj
	 */
	public void delete(C obj);

	/**
	 * 批量删除一个List里的全部对象
	 * 
	 * @param objs
	 */
	public void deleteBatch(List<C> objs);

	/**
	 * 删除ID在列表中的所有记录,返回已删除的记录数.
	 * 
	 * @param ids ID的数组

	 * @return 已删除的记录数.
	 */
	public int deleteBatch(PK[] ids);

	/**
	 * 删除ID在列表中加上where判断语句的所有记录

	 * 
	 * @param ids 要删除的ID数组
	 * @param whereQuery where判断语句
	 * @return 已删除的记录数

	 */
	public int deleteBatch(PK[] ids, String whereQuery);

	/**
	 * 根据ID删除一个对象,返回影响的记录数.
	 * 
	 * @param id
	 * @return
	 */
	public int delete(PK id);

	/**
	 * 列表所有的对象
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<C> findAll();

	/**
	 * 根据querySQL和参数查找 <code>
	 * 	find("FROM ClassName o WHERE o.name = ? AND o.age = ?","chenxingji" , "11");
	 * </code>
	 * 
	 * @param query
	 * @param os SQL中的参数,对应SQL中的问号
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(String query, Object... os);

	/**
	 * 根据querySQL和参数查找 <br>
	 * <code>
	 * 	find(100,"FROM ClassName o WHERE o.name = ? AND o.age = ?","chenxingji" , 11);
	 * </code>
	 * 
	 * @param query
	 * @param maxResult 搜索的最大记录

	 * @param os SQL中的参数,对应SQL中的问号
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(int maxResult, String query, Object... os);

	/**
	 * 根据querySQL查找 <code>
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(String query);

	/**
	 * 根据querySQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param query
	 * @param os SQL语句中的参数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public C uniqueFind(String query, Object... os);

	/**
	 * 根据querySQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param query
	 * @return 查找到多个对象只返回第一个,如果查找不到返回null
	 */
	@SuppressWarnings("unchecked")
	public C uniqueFind(String query);

	/**
	 * 执行一条HQL语句(DELETE,UPDATE...)
	 * 
	 * @param query
	 * @param os 参数
	 * @return 返回影响记录数

	 */
	public int executeQuery(String query, Object... os);

	/**
	 * 执行一条HQL语句(DELETE,UPDATE...)
	 * 
	 * @param query HQL 语句
	 * @param os
	 * @return 返回影响记录数

	 */
	public int executeQuery(String query);

	/**
	 * 根据对象的属性和值查找

	 * 
	 * @param propName 属性名
	 * @param value 属性值

	 * @return
	 */
	public List<C> findByProp(String propName, Object value);

	/**
	 * 根据ID查找
	 * 
	 * @param pk
	 * @return
	 */
	public C findById(PK pk);

	/**
	 * 根据ID查找某一个PersistenceObject的对象

	 * 
	 * @param pk
	 * @para po 返回的DTO
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T findById(Class<T> po, Serializable pk);

	/**
	 * 传入一条select count(*)的SQL语句,返回记录数

	 * 
	 * @param query
	 * @param os SQL语句的参数

	 * @return
	 */
	public int countQuery(String query, Object... os);

	/**
	 * 传入一条select count(*)的SQL语句,返回记录数

	 * 
	 * @param query
	 * @return
	 */
	public int countQuery(String query);

	/**
	 * 根据querySQL和参数查找,参数可以是Collection或数组

	 * 
	 * @param query HQL语句
	 * @param paramNames 参数的名字

	 * @param values 值

	 * @return 结果列表
	 */
	public List<C> findByNamedParam(String query, String paramName, Object value);

	/**
	 * 根据querySQL和参数查找,参数可以是Collection或数组<BR>
	 * 参数个数要与值的个数相等
	 * 
	 * @param query HQL语句
	 * @param paramNames 参数的名字(数组)
	 * @param values 值(数组)
	 * @return 结果列表
	 */
	public List<C> findByNamedParam(String query, String[] paramNames,
			Object[] values);

	/**
	 * 根据字段名,字段值查找不等于传入ID的数据<br>
	 * 一般在更新的时候使用该方法,某一个字段不能重复但不等要更新的ID
	 * 
	 * @param propName 字段名

	 * @param propValue 字段值

	 * @param id 不等于的ID
	 * @return 对象列表
	 */
	public List<C> findByPropExceptPK(String propName, Object propValue, PK id);

	/**
	 * 传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @param form
	 * @return
	 */
	public PagerResult<C> findByCondision(ISearchForm form);

	/**
	 * 批量删除
	 * 
	 * @param delSql 删除语句
	 * @return
	 */
	public int deleteBatch(final String delSql);

	/**
	 * 执行DELETE 和 UDPATE 的SQL语句
	 * 
	 * @param queryString HQL 语句 ,paramNames和values记录数要一样

	 * @param paramNames 传入的参数

	 * @param values 传入的值

	 * @return 影响的记录数
	 */
	public int bulkUpdateByNamedParam(final String queryString,
			final String[] paramNames, final Object[] values);

	/**
	 * 执行DELETE 和 UDPATE 的SQL语句
	 * 
	 * @param queryString HQL 语句
	 * @param paramNames 传入的参数

	 * @param values 传入的值

	 * @return 影响的记录数
	 */
	public int bulkUpdateByNamedParam(final String queryString,
			final String paramNames, final Object values);

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param sql SQL语句
	 * @return 数据的列表

	 */
	public List<Object[]> findBySQL(final String sql);

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql HQL语句
	 * @return 对象数组
	 */
	public List<Object[]> findByHQL(String hql);

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql HQL语句
	 * @param values 参数,对应HQL语句中的?
	 * @return 对象数组
	 */
	public List<Object[]> findByHQL(String hql, Object... values);

	/**
	 * 创建(增加)的时候判断某一属性是否存在

	 * 
	 * @param propName 属性名
	 * @param propValue 属性值

	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForCreate(String propName, Object propValue);

	/**
	 * 创建(增加)的时候判断某一属性是否存在

	 * 
	 * @param propName 属性名数组
	 * @param propValue 属性值数组

	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForCreate(String[] propName, Object[] propValue);

	/**
	 * 更新一时候判断某一属性是否存在(判断时不包括要更新对象的ID)
	 * 
	 * @param propName 属性名
	 * @param propValue 属性值

	 * @param id ID值

	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForUpdate(String propName, Object propValue,
			PK id);
	/**
	 * 更新一时候判断某一属性是否存在(判断时不包括要更新对象的ID)
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            属性值
	 * 
	 * @param id
	 *            ID值
	 * 
	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForUpdate(String[] propName,
			Object[] propValue, PK id) ;
	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql HQL语句
	 * @return 对象数组
	 */
	@SuppressWarnings("unchecked")
	public Object[] uniqueFindByHQL(String hql);

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql HQL语句
	 * @param values 参数,对应HQL语句中的?
	 * @return 对象数组
	 */
	@SuppressWarnings("unchecked")
	public Object[] uniqueFindByHQL(String hql, Object... values);

	/**
	 * 根据HQL和参数查找 <br>
	 * 
	 * <pre>
	 * find(
	 * 		100,
	 * 		User.class,
	 * 		&quot;SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?&quot;,
	 * 		&quot;chenxingji&quot;, &quot;11&quot;);
	 * </pre>
	 * 
	 * @param <T> 返回列表对象里放的类别

	 * @param maxResult 搜索的最大记录

	 * @param query HQL语句
	 * @param os HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表

	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> find(int maxResult, Class<T> clazz, String query,
			Object... os);

	/**
	 * 根据HQL和参数查找 <br>
	 * 
	 * <pre>
	 * find(
	 * 		User.class,
	 * 		&quot;SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = 'chenxingji' AND o.age = 11&quot;);
	 * </pre>
	 * 
	 * @param <T> 返回列表对象里放的类别

	 * @param maxResult 搜索的最大记录

	 * @param query HQL语句
	 * @return 泛型为T的列表

	 */
	public <T> List<T> find(Class<T> clazz, String query);

	/**
	 * 根据HQL和参数查找 <br>
	 * 
	 * <pre>
	 * find(
	 * 		User.class,
	 * 		&quot;SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?&quot;,
	 * 		&quot;chenxingji&quot;, &quot;11&quot;);
	 * </pre>
	 * 
	 * @param <T> 返回列表对象里放的类别

	 * @param query HQL语句
	 * @param os HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表

	 */
	public <T> List<T> find(Class<T> clazz, String query, Object... os);

	/**
	 * 断言某ID记录是否存在,如果不存在就throws AppException
	 * 
	 * @param id 记录的ID
	 * @return TODO
	 * @throws AppException
	 */
	public C assertExists(PK id) throws AppException;

	/**
	 * 断言某ID记录是否存在,如果不存在 throws AppException ,异常的内容为msgCode
	 * 
	 * @param id 记录的ID
	 * @param msgCode 异常编码(如:app.modulename.001)
	 * @throws AppException
	 */
	public C assertExists(PK id, String msgCode) throws AppException;

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName 属性名
	 * @param propValue 该属性的值

	 * @param msgCode 异常编码
	 * @throws AppException 新增时如果记录重复,则throw 该异常

	 */
	public void assertExistsForCreate(String propName, Object propValue,
			String msgCode) throws AppException;

	/**
	 * 更新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName 属性名
	 * @param propValue 该属性的值

	 * @param id 要更新的记录的 ID
	 * @param msgCode 异常编码
	 * @throws AppException 更新时如果记录重复,则throw 该异常

	 */
	public void assertExistsForUpdate(String propName, Object propValue, PK id,
			String msgCode) throws AppException;

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @param searchForm 搜索条件,并包含分页信息

	 * @param clazz 返回结果的类型

	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondision(final ISearchForm searchForm,
			final Class<T> clazz);

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器) <BR>
	 * 并用构造函数进行构造

	 * 
	 * @param searchForm 搜索条件,并包含分页信息

	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondisionAndCast(
			final ISearchForm searchForm, final Class<T> clazz);

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName[] 属性名 数组
	 * @param propValue[] 该属性的值 数组
	 * @param msgCode 异常编码
	 * @throws AppException 新增时如果记录重复,则throw 该异常

	 */
	public void assertExistsForCreate(String[] propName, Object[] propValue,
			String msgCode) throws AppException;

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName[] 属性名 数组
	 * @param propValue[] 该属性的值 数组
	 * @param msgCode 异常编码
	 * @throws AppException 新增时如果记录重复,则throw 该异常

	 */
	public void assertExistsForUpdate(String[] propName, Object[] propValue,
			PK id, String msgCode) throws AppException;

	/**
	 * 根据HQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param class <T> 要返回的对象的类型

	 * @param query
	 * @param os SQL语句中的参数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T uniqueFind(Class<T> clazz, String query, Object... os);

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param cls 要返回的对象的类型

	 * @param sql SQL语句
	 * @return 数据的列表

	 */
	public <T> List<T> findBySQL(Class<T> cls, String sql);

	/**
	 * 执行SQL语句
	 * 
	 * @param sql SQL语句
	 * @param args 参数
	 * @return 影响记录数

	 */
	public int executeBySQL(final String sql, final Object... args);

	/**
	 * 执行SQL语句
	 * 
	 * @param sql SQL语句
	 * @return
	 */
	public int executeBySQL(final String sql);

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组

	 * 
	 * @param cls 返回值里List的类型

	 * @param query HQL语句
	 * @param paramNames 参数的名字

	 * @param values 值

	 * @return 结果列表
	 */
	public <T> List<T> findByNamedParam(Class<T> cls, String query,
			String paramName, Object value);

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组<BR>
	 * 参数个数要与值的个数相等
	 * 
	 * @param cls 返回值里List的类型

	 * @param query HQL语句
	 * @param paramNames 参数的名字(数组)
	 * @param values 值(数组)
	 * @return 结果列表
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findByNamedParam(Class<T> cls, String query,
			String[] paramNames, Object[] values);

	/**
	 * 根据ID查找
	 * 
	 * @param pk Id的值

	 * @param lockMode 锁表的级别,参数hibernate文档
	 * @return
	 */
	public C findById(PK pk, LockMode lockMode);

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T> 返回列表对象里放的类别

	 * @param query HQL语句
	 * @param lockMode 锁表的类型

	 * @param lockAlias
	 * @param os HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表

	 */
	@SuppressWarnings("unchecked")
	public List<C> find(final LockMode lockMode, final String lockAlias,
			final String query, final Object... os);

	@SuppressWarnings("unchecked")
	public List<C> find(final LockMode lockMode, final String lockAlias,
			final String query);

	/**
	 * 根据Store procedure
	 * SQL语句进行查找(只处理有返回值[结果集],最后一个参数为CURSOR,SP参数不可是集合类型,比如Byte[],Int[])
	 * findBySP(Class, "{ call PKG_PERSONAL_LOAN.findReturnMoney(?,?)}",
	 * stateid);
	 * 
	 * @param callsql SP SQL语句
	 * @return 数据的列表

	 * @author 田才寿

	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findBySP(final Class<T> persistentClass,
			final String callsql, final Object... pi);

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param sql
	 * @param args 参数
	 * @return
	 */
	public List<Object[]> findBySQL(final String sql, final Object... args);

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param cls 要返回的对象的类型

	 * @param sql SQL语句
	 * @param args 参数
	 * @return 数据的列表

	 */
	public <T> List<T> findBySQL(Class<T> cls, String sql, Object... args);

	/**
	 * 用Store procedure SQL语句来更新DB updateBySP("{ call
	 * PKG_PERSONAL_LOAN.REFRESHLOANSTATUS(?)}", stateid);
	 * 
	 * @param callsql SP SQL语句
	 * @author 田才寿

	 */
	public void updateBySP(final String callsql, final Object... pi);

	/**
	 * 用NamedQuery方法查询数据
	 * SQL语句配置到hbm.xml中,具体实例参考com.htf.gjj.pl.loanbusiness.batchreturn.dto下的
	 * ReturnBillDetailFO.hbm.xml文件 调用List list =
	 * batchReturnDAO.findByNamedQuery("findLoanReturnDetailByReturnBillId",
	 * returnBillId, returnBillId);
	 * 
	 * @params 参数
	 * @author 田才寿

	 */
	public List findByNamedQuery(String namedQuery, Object... params);

	/**
	 * 强制更新Session缓存
	 * 
	 * @params 参数
	 * @author 田才寿

	 */
	public void refreshSession();

	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondisionAndCast(Class<?> searchClazz, ISearchForm searchForm,
			Class<T> retClazz);

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @searchClass 搜索的DTO类

	 * @param searchForm 搜索条件,并包含分页信息

	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondision(final Class<T> searchClass, final ISearchForm searchForm);
	
	/***
	 * 在SQL中,各类型数据库的日期转字符串

	 * @param field 要转换的字段
	 * @param format 格式
	 * @param len 转换后的长度
	 * @return
	 */
	public String sqlDateToStr(String field, String format, int len);
	
	/***
	 * 在SQL中,各类型数据库的字符串转日期

	 * @param field 要转换的字段
	 * @param format 格式
	 * @return
	 */
	public String sqlStrToDate(Date source, String format);
	/***
	 * 在SQL中,字段内容为NULL的函数

	 * @return
	 */
	public String sqlIsNull();
	
	/**
	 * 获取当前数据库的类型(DB2 , oracle,mssql....)
	 * @return
	 */
	public DatabaseType getDatabaseType();
	/**
	 * 批量新增或保存
	 */
	public void saveOrUpdateBatch(Collection<C> objs);

	/**
	 * 根据ID查找
	 * 
	 * @param pk
	 * @return
	 */
	public List<C> findByIds(PK[] pks);

	public void clearSession();
	public void flushSession();

	/**
	 * 根据一个Map动态更新一个对象
	 * @param entityName 实体的名字,对应hbm.xml class 元素中的 entity-name属性
	 * @param fieldValueMap 属性名和值之间的映射
	 */
	public void dynamicUpdate(final String entityName, final Map<String, Object> fieldValueMap);

	/**
	 * 根据一个Map动态新增一个对象
	 * @param entityName 实体的名字,对应hbm.xml class 元素中的 entity-name属性
	 * @param fieldValueMap 属性名和值之间的映射
	 */
	public Object dynamicSave(final String entityName, final Map<String, Object> fieldValueMap);

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		100,
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param firstResult
	 *            开始的记录
	 * @param maxResult
	 *            搜索的最大记录
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表
	 * 
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> find(int firstResult, int maxResult, Class<T> clazz, String query,
			Object... os);

	public List<C> find(int firstResult, int maxResult, String query, Object... os);
	
	/**
	 * 格式化sql语句 in 的格式
	 */
	public  String getStringForHQL(Integer[] longIDs) ;

}
